package com.wondertek.mam.tag.web.rest;

import com.wondertek.mam.tag.config.Constant;
import com.wondertek.mam.tag.config.ScheduleTask;
import com.wondertek.mam.tag.domain.ArticleBean;
import com.wondertek.mam.tag.domain.TagDB;
import com.wondertek.mam.tag.repository.TagRepository;
import com.wondertek.mam.tag.service.TagService;
import com.wondertek.mam.tag.web.rest.util.RespBody;
import com.wondertek.mam.tag.web.rest.vm.GroupVM;
import com.wondertek.mam.tag.web.rest.vm.ReqPostTag;
import com.wondertek.mam.tag.web.rest.vm.ReqPutTag;
import org.apdplat.word.util.AutoDetector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 标签接口
 * Created by wangdongxu on 2017-09-05 下午 14:18:20.
 */
@RestController
public class TagController {
    private static final Logger LOGGER = LoggerFactory.getLogger(TagController.class);

    @Autowired
    private TagRepository tagRepository;
    @Autowired
    private TagService tagService;

    /**
     * POST 为文字添加标签
     * @param article 文章
     * @return 成功20000
     *         错误00001 文章没有得到匹配结果
     *         错误00002 不能为空字段
     */
    @PostMapping("tag")
    public ResponseEntity getTextTag(@RequestBody ArticleBean article){
        if (article.getText()==null||article.getText().isEmpty()||article.getTitle()==null||article.getTitle().isEmpty()) {
            return ResponseEntity.ok(RespBody.build("002", "字段不能为空"));
        }
        RespBody respBody;
        //更新分词库锁
        synchronized (Constant.class) {
            //加载词库锁
            synchronized (AutoDetector.class) {
                respBody = tagService.getArticleTag(article);
            }
        }
        return ResponseEntity.ok(respBody);
    }

    @PutMapping("test")
    public ResponseEntity test (@Validated @RequestBody ReqPostTag reqPostTag)  {
        System.out.println(reqPostTag);
        return ResponseEntity.ok(RespBody.ok());
    }

    /**
     * 获取标签
     * @param tag 标签
     * @param score 等级
     * @param hot 热词
     * @param createTimeStart 创建开始时间
     * @param createTimeEnd 创建结束时间
     * @param updateTimeStart 更新开始时间
     * @param updateTimeEnd 更新结束时间
     * @param protectedTimeStart 受保护开始时间
     * @param protectedTimeEnd 受保护结束时间
     * @param rows 条数
     * @param page 页数
     * @return ResponseEntity
     */
    @GetMapping("/tags")
    public ResponseEntity getTags(@RequestParam(required = false) String tag,
                                  @RequestParam(required = false) Integer score,
                                  @RequestParam(required = false) Boolean hot,
                                  @RequestParam(required = false) LocalDateTime createTimeStart,
                                  @RequestParam(required = false) LocalDateTime createTimeEnd,
                                  @RequestParam(required = false) LocalDateTime updateTimeStart,
                                  @RequestParam(required = false) LocalDateTime updateTimeEnd,
                                  @RequestParam(required = false) LocalDate protectedTimeStart,
                                  @RequestParam(required = false) LocalDate protectedTimeEnd,
                                  @RequestParam(required = false,defaultValue = "0") Integer groupId, //0全部，-1未分组
                                  @RequestParam(required = false,defaultValue = "20") Integer rows,
                                  @RequestParam(required = false,defaultValue = "1") Integer page,
                                  @RequestParam(required = false,defaultValue = "asc") String sord,
                                  @RequestParam(required = false,defaultValue = "tag") String sidx
                                  ){

        if (rows<1){
            return ResponseEntity.ok(RespBody.build("00001","参数错误").setDescription("rows"));
        }
        if (page<1){
            return ResponseEntity.ok(RespBody.build("00001","参数错误").setDescription("page"));
        }
        if (!sord.equals("asc")&&!sord.equals("desc")){
            return ResponseEntity.ok(RespBody.build("00001","参数错误").setDescription("sord"));
        }
        if (!Arrays.asList("tag","id","hot","createTime","updateTime","protectedTime").contains(sidx)){
            return ResponseEntity.ok(RespBody.build("00001","参数错误").setDescription("sidx"));
        }
        Sort sort;
        Sort.Order orderId = new Sort.Order(Sort.Direction.ASC,"id");
        if (sord.equals("desc")) {

            sort = new Sort(new Sort.Order(Sort.Direction.DESC, sidx),orderId);
        }
        else {
            sort = new Sort(new Sort.Order(Sort.Direction.ASC, sidx), orderId);
        }

        Pageable pageable = new PageRequest(page-1,rows,sort);
        Page<TagDB> tags = tagService.getTags(tag, score, hot, createTimeStart, createTimeEnd, updateTimeStart, updateTimeEnd, protectedTimeStart, protectedTimeEnd, groupId,pageable);
        return ResponseEntity.ok(RespBody.ok(tags.getContent()).setTotalElements((int)tags.getTotalElements()).setTotalPages(tags.getTotalPages()));
    }

    /**
     * 修改标签
     * @param tags 修改的内容
     * @return ResponseEntity
     *         20000 成功
     *         00001 参数有误
     */
    @PostMapping("/tags")
    public ResponseEntity postTags(@RequestBody List<ReqPostTag> tags){
        List<Integer> collectIds = tags.stream().map(ReqPostTag::getId).collect(Collectors.toList());
        int count = tagRepository.findAllByIdInAndGroupId(collectIds, -1).size();
        if (count!=tags.size()){
            return ResponseEntity.ok(RespBody.build("00001", "参数有误"));
        }
        for (ReqPostTag reqPostTag: tags) {
            if (reqPostTag.getId()==null||(reqPostTag.getScore()!=null&&(reqPostTag.getScore()>5||reqPostTag.getScore()<1))) {
                return ResponseEntity.ok(RespBody.build("00001", "参数有误"));
            }
        }
        tagService.postTags(tags);
        ScheduleTask.refreshFlag = true;
        return ResponseEntity.ok(RespBody.ok());
    }

    /**
     * 标签升级为组名
     * @param id id
     * @return 00001 参数不能为空
     *         00002 classId不存在
     *         00003 id错误
     *
     */
    @GetMapping("/tag2Group")
    public ResponseEntity tag2Group(@RequestParam(required = true) Integer id,@RequestParam(required = true) Integer classId){
        if (id==null||classId==null){
            return ResponseEntity.ok(RespBody.build("00001","参数不能为空"));
        }
        if (!Constant.TAG_CLASS.isClassId(classId)){
            return ResponseEntity.ok(RespBody.build("00002","classId不存在"));
        }
        TagDB one = tagRepository.findOne(id);
        if (one ==null) return ResponseEntity.ok(RespBody.build("00003","id错误"));
        one.setGroupId(0);
        one.setClassId(classId);
        one.setScore(4);
        one.setHot(false);
        one.setProtectedTime(LocalDate.MAX);
        tagRepository.save(one);
        return ResponseEntity.ok(RespBody.ok());
    }
    /**
     * 添加
     * @param reqPutTags 添加的列表
     * @return ResponseEntity
     *         20000 成功
     *         00001 参数有误
     *         00002 有重复元素
     *         00003 groupId不存在
     */
    @PutMapping("/tags")
    public ResponseEntity putTags(@RequestBody List<ReqPutTag> reqPutTags){
        for (ReqPutTag reqPutTag: reqPutTags) {
            if (reqPutTag.getTag()==null||reqPutTag.getTag().isEmpty()||reqPutTag.getScore()==null||reqPutTag.getScore()>5||reqPutTag.getScore()<1||reqPutTag.getProtectedTime()==null) {
                return ResponseEntity.ok(RespBody.build("00001", "参数有误,或缺失参数"));
            }
        }
        List<String> reqTags = reqPutTags.stream().map(ReqPutTag::getTag).collect(Collectors.toList());
        List<String> dBtags = tagRepository.findAllByTagIn(reqTags).stream().map(TagDB::getTag).collect(Collectors.toList());
        //判断是否有重复
        if (dBtags.size()!=0){
            List<String> collect = reqTags.stream().filter(dBtags::contains).collect(Collectors.toList());
            return ResponseEntity.ok(RespBody.build("00001","已经存在").setData(collect));
        }
        //判断分组的id是否都合法
        Set<Integer> addGroupIds = reqPutTags.stream()
            .filter(tag -> tag.getGroupId() != null&&tag.getGroupId()!=-1)
            .map(ReqPutTag::getGroupId)
            .collect(Collectors.toSet());
        System.out.println(addGroupIds);
        tagRepository.findAllByIdInAndGroupId(addGroupIds,0).forEach(tag -> addGroupIds.remove(tag.getId()));
        System.out.println(addGroupIds);
        if (addGroupIds.size()!=0){
            return ResponseEntity.ok(RespBody.build("00003","groupId不存在"));
        }
        List<TagDB> saveTagDBs = reqPutTags.stream()
            .map(reqPutTag -> new TagDB(reqPutTag.getTag(), LocalDateTime.now(),
                LocalDateTime.now(), reqPutTag.getScore(),
                reqPutTag.getScore() == 5, reqPutTag.getProtectedTime(),reqPutTag.getGroupId()==null?-1:reqPutTag.getGroupId(),null))
            .collect(Collectors.toList());
        //保存
        List<TagDB> save = tagRepository.save(saveTagDBs);
        LOGGER.debug("添加"+reqTags);
        ScheduleTask.refreshFlag = true;
        return ResponseEntity.ok(RespBody.ok(save.stream().map(TagDB::getId).collect(Collectors.toList())));
    }

    /**
     * 删除
     * @param ids 主键
     * @return ResponseEntity
     *         00001 不能删除组
     */
    @DeleteMapping("/tags")
    public ResponseEntity delTags(@RequestBody List<Integer> ids){
        List<TagDB> all = tagRepository.findAll(ids);
        long count = all.stream().filter(tagDB -> tagDB.getGroupId() == 0).count();
        if (count!=0L){
            return ResponseEntity.ok(RespBody.build("00001","不能删除组"));
        }
        tagRepository.delete(all);
        List<Integer> result = all.stream().map(TagDB::getId).collect(Collectors.toList());
        ScheduleTask.refreshFlag = true;
        return ResponseEntity.ok(RespBody.ok(result));
    }

    /**
     * 获取分组
     * @param classId 分类id
     * @return ResponseEntity
     */
    @GetMapping("/groups")
    public ResponseEntity getGroups(@RequestParam Integer classId){
        List<GroupVM> result = tagRepository.findAllByClassIdAndGroupId(classId, 0)
            .stream().map(tagDB -> new GroupVM(tagDB.getId(),tagDB.getTag(),tagDB.getClassId())).collect(Collectors.toList());
        return ResponseEntity.ok(RespBody.ok(result));
    }

    /**
     * 移除分组
     * @param ids 分组id
     * @return 00001 无法移除非组对象
     *
     */
    @DeleteMapping("/groups")
    public ResponseEntity delGroup(@RequestBody List<Integer> ids){
        int notGroup = tagRepository.findAllByIdInAndGroupId(ids,0).size();
        if (notGroup!=ids.size()){
            return ResponseEntity.ok(RespBody.build("00001","无法移除非组对象"));
        }
        tagService.delGroup(ids);
        return ResponseEntity.ok(RespBody.ok());
    }

    /**
     *
     * @param groups 组
     * @return 00001 组不能为空
     *         00002 组名不能为空
     *         00003 组名不能重复
     *         00004 组名已存在
     */
    @PutMapping("/groups")
    public ResponseEntity putGroups(@RequestBody List<GroupVM> groups){
        if (groups.size()==0){
            return ResponseEntity.ok(RespBody.build("00001","组不能为空"));
        }
        final boolean[] check = {false,false};
        List<String> putGroupName = new ArrayList<>();
        List<TagDB> groupsDB = new ArrayList<>();
        groups.forEach(groupVM -> {
            if (groupVM.getName() == null || groupVM.getName().equals("") || groupVM.getClassId() == null || !Constant.TAG_CLASS.isClassId(groupVM.getClassId())){
                check[0] = true;
            }
            if (putGroupName.contains(groupVM.getName())){
                check[1] = true;
            }
            putGroupName.add(groupVM.getName());
            groupsDB.add(new TagDB(groupVM.getName(),LocalDateTime.now(),LocalDateTime.now(),4,false,LocalDate.MAX,0,groupVM.getClassId()));
        });
        if (check[0]){
            return ResponseEntity.ok(RespBody.build("00002","组名不能为空"));
        }
        if (check[1]){
            return ResponseEntity.ok(RespBody.build("00003","组名不能重复"));
        }
        List<TagDB> allByTagIn = tagRepository.findAllByTagIn(putGroupName);
        if (allByTagIn.size()!=0){
            return ResponseEntity.ok(RespBody.build("00004","组名已存在").setData(allByTagIn.stream().map(TagDB::getTag).collect(Collectors.toList())));
        }
        tagRepository.save(groupsDB);
        ScheduleTask.refreshFlag = true;
        return ResponseEntity.ok(RespBody.ok());
    }

    /**
     * 从分组中删除
     * @param ids
     * @return
     */
    @PostMapping("/delTagFromGroup")
    public ResponseEntity delTagFromGroup(@RequestBody List<Integer> ids){
        List<TagDB> collect = tagRepository.findAll(ids)
            .stream()
            .filter(tagDB -> tagDB.getGroupId() != null && tagDB.getGroupId() != 0 && tagDB.getGroupId() != -1)
            .map(tagDB -> {
                tagDB.setGroupId(-1);
                tagDB.setClassId(null);
                return tagDB;
            })
            .collect(Collectors.toList());
        tagRepository.save(collect);
        return ResponseEntity.ok(RespBody.ok());
    }

    /**
     * 添加标签到分组
     * @param adds
     * @return
     */
    @PostMapping("/addTagToGroup/{groupId}")
    public ResponseEntity addTagFromGroup(@PathVariable Integer groupId,@RequestBody(required = true) List<Integer> adds){
        if (!tagRepository.exists(groupId)) return ResponseEntity.ok(RespBody.build("00001","groupId不存在"));
        List<TagDB> collect = tagRepository.findAll(adds).stream().map(tagDB -> {
            tagDB.setGroupId(groupId);
            return tagDB;
        }).collect(Collectors.toList());
        tagRepository.save(collect);
        return ResponseEntity.ok(RespBody.ok());
    }
    /**
     * 获取分组集
     * @return ResponseEntity
     */
    @GetMapping("/classes")
    public ResponseEntity getClassIds(){
        Map<Integer,List<GroupVM>> classes = new HashMap<>();
        for (Constant.TAG_CLASS tagClass:Constant.TAG_CLASS.values()) {
            int classId = tagClass.getValue();
            List<GroupVM> result = tagRepository.findAllByClassIdAndGroupId(classId, 0)
                .stream().map(tagDB -> new GroupVM(tagDB.getId(),tagDB.getTag(),tagDB.getClassId())).collect(Collectors.toList());
            classes.put(tagClass.getValue(),result);
        }
        return ResponseEntity.ok(RespBody.ok(classes));
    }

}
